<template>
  <div
    class="cameraClass"
    :style="{ width: jingtouW + 'px', height: jingtouH + 'px' }"
  >
    <img
      v-if="imgFlag"
      :src="pegSrc"
      alt="视频流未播放"
      style="width: 100%; height: 100%"
    />
    <canvas
      ref="canvas"
      :width="jingtouW"
      :height="jingtouH"
      @mousedown="handleStart"
      @mousemove="handleMove"
      @mouseup="handleEnd"
      @mouseleave="handleEnd"
      @touchstart="handleStart"
      @touchmove="handleMove"
      @touchend="handleEnd"
      @touchcancel="handleEnd"
      style="touch-action: none; -ms-touch-action: none"
    ></canvas>
  </div>
</template>

<script setup>
import { startVideo } from '../http/video'
import { ref, onMounted, defineExpose, watch, onUnmounted } from 'vue'
// 确保引入 ElMessage（若全局注册可省略）
import { ElMessage } from 'element-plus'

let imgFlag = ref(true)

const props = defineProps({
  jingtouW: {
    type: Number,
    default: 0,
    validator: (val) => val >= 0, // 避免负尺寸
  },
  jingtouH: {
    type: Number,
    default: 0,
    validator: (val) => val >= 0,
  },
  dialogCameraVisible: false,
})

const canvas = ref(null)
const ctx = ref(null)
const pegSrc = ref(
  import.meta.env.VITE_APP_BASE_API +
    `api/video/stream.mjpeg?timestamp=${Date.now()}`,
)

// 矩形数据：新增触摸偏移量，解决拖动"跳变"
const rectangle = ref({
  points: [],
  activePoint: null,
  isDragging: false,
  offsetX: 0, // 触摸点与控制点的X偏移
  offsetY: 0, // 触摸点与控制点的Y偏移
})

const pointRadius = 15

function playVideoFn() {
  imgFlag.value = false
  startVideo({})
    .then((res) => {
      imgFlag.value = true
      ElMessage({
        message: '播放成功',
        type: 'success',
      })
    })
    .catch((err) => {
      imgFlag.value = true
      ElMessage.error(`播放失败：${err.message || '网络异常'}`)
    })
}

function initPoint() {
  rectangle.value.points = []
  // 避免控制点超出画布（适配触摸交互）
  const min = pointRadius
  const maxX = props.jingtouW - pointRadius
  const maxY = props.jingtouH - pointRadius
  rectangle.value.points.push({ x: min, y: min }) // 左上
  rectangle.value.points.push({ x: maxX, y: min }) // 右上
  rectangle.value.points.push({ x: maxX, y: maxY }) // 右下
  rectangle.value.points.push({ x: min, y: maxY }) // 左下
}

const initCanvas = () => {
  if (!canvas.value) return
  ctx.value = canvas.value.getContext('2d')
  draw()
}

const draw = () => {
  if (!ctx.value || rectangle.value.points.length === 0) return
  // 清空画布
  ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
  // 绘制矩形
  ctx.value.beginPath()
  ctx.value.moveTo(rectangle.value.points[0].x, rectangle.value.points[0].y)
  for (let i = 1; i < rectangle.value.points.length; i++) {
    ctx.value.lineTo(rectangle.value.points[i].x, rectangle.value.points[i].y)
  }
  ctx.value.closePath()
  ctx.value.strokeStyle = 'cornflowerblue'
  ctx.value.lineWidth = 2
  ctx.value.stroke()
  // 绘制控制点（触摸交互需清晰可见）
  ctx.value.fillStyle = 'red'
  rectangle.value.points.forEach((point) => {
    ctx.value.beginPath()
    ctx.value.arc(point.x, point.y, pointRadius, 0, Math.PI * 2)
    ctx.value.fill()
  })
}

const isPointInControlPoint = (x, y, point) => {
  return Math.sqrt((x - point.x) ** 2 + (y - point.y) ** 2) <= pointRadius
}

// 核心：统一获取鼠标/触摸坐标（Windows触摸关键适配）
const getEventPos = (e) => {
  if (!canvas.value) return { x: 0, y: 0 }
  const rect = canvas.value.getBoundingClientRect()
  let clientX, clientY

  // 处理触摸事件：从touches获取坐标（Windows触摸的核心）
  if (e.type.startsWith('touch')) {
    e.preventDefault() // 阻止页面滚动/缩放，避免干扰触摸
    const touch = e.touches[0] || e.changedTouches[0] // 取第一个触摸点
    clientX = touch.clientX
    clientY = touch.clientY
  } else {
    // 处理鼠标事件
    clientX = e.clientX
    clientY = e.clientY
  }

  // 计算相对于画布的坐标
  return {
    x: clientX - rect.left,
    y: clientY - rect.top,
  }
}

// 统一处理鼠标按下/触摸开始
const handleStart = (e) => {
  const { x, y } = getEventPos(e)
  // 检查是否点击控制点
  for (let i = 0; i < rectangle.value.points.length; i++) {
    if (isPointInControlPoint(x, y, rectangle.value.points[i])) {
      rectangle.value.activePoint = i
      rectangle.value.isDragging = true
      // 计算偏移量：解决触摸时控制点"跳变"
      rectangle.value.offsetX = x - rectangle.value.points[i].x
      rectangle.value.offsetY = y - rectangle.value.points[i].y
      break
    }
  }
}

// 统一处理鼠标移动/触摸移动
const handleMove = (e) => {
  if (!rectangle.value.isDragging || rectangle.value.activePoint === null)
    return
  const { x, y } = getEventPos(e)
  const activeIdx = rectangle.value.activePoint
  const points = rectangle.value.points

  // 用偏移量修正坐标，确保触摸拖动精准
  const newX = x - rectangle.value.offsetX
  const newY = y - rectangle.value.offsetY

  // 限制控制点在画布内（避免触摸拖出边界）
  const min = pointRadius
  const maxX = props.jingtouW - pointRadius
  const maxY = props.jingtouH - pointRadius
  points[activeIdx].x = Math.max(min, Math.min(newX, maxX))
  points[activeIdx].y = Math.max(min, Math.min(newY, maxY))

  // 重绘画布
  draw()
}

// 统一处理鼠标抬起/触摸结束
const handleEnd = (e) => {
  // 触摸结束需额外阻止默认行为
  if (e.type.startsWith('touch')) e.preventDefault()
  rectangle.value.isDragging = false
  rectangle.value.activePoint = null
}

const getPointsPosition = () => {
  return rectangle.value.points.map((p) => ({ x: p.x, y: p.y }))
}

onMounted(() => {
  initPoint()
  initCanvas()
  // 监听窗口缩放，重新适配画布
  window.addEventListener('resize', initCanvas)
})

// 清理监听，避免内存泄漏
onUnmounted(() => {
  window.removeEventListener('resize', initCanvas)
})

defineExpose({
  getPointsPosition,
})

watch(
  () => props.dialogCameraVisible,
  (val) => {
    if (val) {
      pegSrc.value = ''
      setTimeout(() => {
        pegSrc.value =
          import.meta.env.VITE_APP_BASE_API +
          `api/video/stream.mjpeg?timestamp=${Date.now()}`
      }, 300)
    }
  },
)
</script>

<style lang="scss" scoped>
canvas {
  width: 100%;
  height: 100%; // 修复原代码仅宽100%的问题，确保画布铺满容器
  border: 1px solid #ccc;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  cursor: pointer; // 提示可交互（触摸/鼠标通用）
}
.points-info {
  margin-top: 20px;
  padding: 10px;
  background-color: #f0f0f0;
  border-radius: 5px;
}
.cameraClass {
  position: relative;
  user-select: none; // 防止触摸时选中文字
}
</style>
